package org.activequant.dao.hibernate;

import java.util.ArrayList;
import java.util.List;

import org.activequant.core.domainmodel.marketscanner.MarketScan;
import org.activequant.core.domainmodel.marketscanner.ScanCriteria;
import org.activequant.dao.IMarketScanDao_old;
import org.activequant.util.exceptions.DaoException;
import org.activequant.util.tools.ArrayUtils;
import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.springframework.dao.DataAccessException;

public class MarketScanDao_old extends DaoSupportBase<MarketScan> implements IMarketScanDao_old {
	Logger log = Logger.getLogger(MarketScanDao_old.class);
	/**
	 * Constructs a MarketScanDao(extends DaoSupportBase&lt;MarketScan&gt; implements IMarketScanDao) whose inherited clazz(Class&lt;T&gt;) is set to <code>MarketScan.class</code>.
	 */
	public MarketScanDao_old() {
		super(MarketScan.class);
	}
	/**
	 * Constructs a MarketScanDao(extends DaoSupportBase&lt;MarketScan&gt; implements IMarketScanDao) whose inherited clazz(Class&lt;T&gt;) is set to <code>MarketScan.class</code>.<br/>
	 * The given sessionFactory(SessionFactory) is used to set its Hibernate SessionFactory and create/initialize the inherited hibernateTemplate(HibernateTemplate) for it.
	 * @param sessionFactory
	 */
	public MarketScanDao_old(SessionFactory sessionFactory) {
		super(MarketScan.class, sessionFactory);
	}
	/**
	 *  Deletes the given entities(List&lt;MarketScan&gt;) instances themselves(including their MarketScanRows).
	 */
	@Override
    public void delete(List<MarketScan> entities) throws DaoException {
		try {		
			//HqlQueries.deleteScanCriteriaEntities(getHibernateTemplate(), entities.toArray(new ScanCriteria[] {}));
			getHibernateTemplate().deleteAll(new ArrayList<MarketScan>(entities));
		} catch (DataAccessException e) {
			throw new DaoException(e);
		}   	
    }
	/**
	 * Deletes all MarketScan instances (including their MarketScanRows).
	 */
	@Override 
	@SuppressWarnings("unchecked")
	public void deleteAll() {
		try {
			List<MarketScan> specs = getHibernateTemplate().loadAll(clazz);
			// hibernate does not support orphan-delete on one-to-one or many-to-one
			//HqlQueries.deleteScanCriteriaEntities(getHibernateTemplate(), specs.toArray(new ScanCriteria[] {}));
			getHibernateTemplate().deleteAll(specs);
		} catch (DataAccessException e) {
			throw new DaoException(e);
		}
	}
	/**
	 * Saves/updates and returns the given entity(ScanCriteria).<br/>
	 * If there was no id, it looks it up by finding an example.
	 */
	@Override
	public MarketScan update(MarketScan entity) {
//		if(!entity.hasId()) {
//			MarketScan storedSpec = super.findByExample(entity);
//			if(storedSpec != null) {
//				entity.setId(storedSpec.getId());
//				return storedSpec;
//			}
//		}
		return super.update(entity);
	}
	/**
	 * Returns the criterias(ScanCriteria[]) whose ScanCode matches the given scanCode(String)
	 */
//	@SuppressWarnings("unchecked")
//	public ScanCriteria[] findByScanCode(final String scanCode) throws DaoException {
//		// TODO Auto-generated method stub
//		return (ScanCriteria[])getHibernateTemplate().execute(new HibernateCallback() {
//			public Object doInHibernate(Session session) throws HibernateException, SQLException {
//				Query query = session.createQuery("from " + ScanCriteria.class.getName() + " where scanCode='" + scanCode + "'");
//				return query.list().toArray(new ScanCriteria[] {});
//			}
//		});
//	}
	/**
	 * Returns the marketScans(MarketScan[]) whose scanCriteria(ScanCriteria) matches the given one
	 */
	@SuppressWarnings("unchecked")
	public MarketScan[] findByScanCriteria(ScanCriteria scanCriteria) throws DaoException {
		// get contract instance
		scanCriteria = lookupIfNeeded(scanCriteria);		
		// find associated candles
		DetachedCriteria criteria = DetachedCriteria.forClass(clazz).add(Expression.eq("scanCriteria", scanCriteria)).addOrder(Order.desc("timeStamp"));	
		List<MarketScan> list = getHibernateTemplate().findByCriteria(criteria);		
		return ArrayUtils.asArray(list, clazz);	
	}
	
	@SuppressWarnings("unchecked")
	private ScanCriteria lookupIfNeeded(ScanCriteria spec) {
		if(spec.hasId()) return spec; // not needed
		List<ScanCriteria> list = getHibernateTemplate().findByExample(spec);
		if(list.size() == 0) {
			log.warn("No ScanCriteria for example found ...");
			return null; 
		} else if(list.size() > 1) {
			throw new IllegalArgumentException("ambiguity: ScanCriteria matches more than one database entity: " + spec);
		}
		spec = list.get(0);
		log.debug("Found ScanCriteria by example, id=" + spec.getId());
		return spec;
	}
}